﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

#include "ExprNode.h"
#include "ExprToken.h"

namespace gcmp
{
    /// \brief 表达式解析器
    ///
    /// 表达式语法结构
    /// exp->state-exp[state-op state-exp]
    /// state-op-> And|OR
    /// state-exp -> simple-exp[comparison-op simple-exp]
    /// comparison-op -> <|=等
    ///
    /// simple-exp -> term{addop term}
    /// addop -> +|-
    /// term -> factor{mulop factor}
    ///
    /// mulop -> *|/
    /// factor -> [-](exp)|[-]number|[-]identifier|function(exp, exp, exp…)
    class ExprCustomParser : public IExprParser
    {
    public:
        ExprCustomParser(IExprEngine* aEngine);
        virtual ~ExprCustomParser();

    public:
        virtual wchar_t* SetExpression(const wchar_t* aValue) override;
        virtual void Evaluate() override;
        virtual ExprDataType ResultType() const override;

        virtual UnitMap ResultUnitType() override;

        virtual ExprNodeData* Result() override;
        virtual bool GetIsNull() const override;
        virtual bool GetIsValid() const override;
        virtual int GetErrorPos() const override;
        virtual EnErrorType GetErrorType() const override;
        virtual const IExprEngine* GetEngine() const override;
        virtual const ExprNode* GetRootNode() const override;
        virtual void Accept(ExprNodeVisitor* pVisitor) const override;
        virtual bool IsCircularReferenced(const wchar_t* tokenName) const override;
        virtual void GetAllReferencedParamNames(std::set<const wchar_t*>& refParamNames) const override;

        virtual std::vector<const wchar_t*> GetExprNodeNames() const override;

        virtual void GetIDNodePositions(const std::wstring& nodeName, std::vector<std::pair<int, int>>& result) const override;

    private:
        // 词法分析相关成员
        /// \brief 匹配一个Token
        ///
        /// param expected Token类型
        void Match(ExprTokenType expected);
        /// \brief 表达式分解为条件表达式
        gcmp::OwnerPtr<ExprNode> Expr();
        /// \brief 条件表达式分解为简单表达式
        gcmp::OwnerPtr<ExprNode> State_Expr();
        /// \brief 将简单表达式分解为加法或减法表达式
        gcmp::OwnerPtr<ExprNode> Simple_Expr();
        /// \brief 将加法或减法表达式分解为乘法或除法表达式
        gcmp::OwnerPtr<ExprNode> Term();
        gcmp::OwnerPtr<ExprNode> Factor();

        void FactorForID(gcmp::OwnerPtr<ExprCustumNode>& p);
        void FactorForIDRef(gcmp::OwnerPtr<ExprCustumNode>& p);
        void FactorForUnaryOperate(gcmp::OwnerPtr<ExprCustumNode>& t);
        void FactorForBool(gcmp::OwnerPtr<ExprCustumNode>& p);
        void FactorForString(gcmp::OwnerPtr<ExprCustumNode>& p);
        void FactorForFloat(gcmp::OwnerPtr<ExprCustumNode>& p);
        void FactorForInt(gcmp::OwnerPtr<ExprCustumNode>& p);
        void FactorForFunction(gcmp::OwnerPtr<ExprCustumNode>& p);

        void ParseError(EnErrorType errorType);

        /// \brief 计算一个节点，包括类型检查
        ///
        /// param node 节点
        /// param aDataProvider 节点数据提供者
        void EvaluateNode(ExprNode* node, IExprNodeDataProvider* aDataProvider);

        void EvaluateNestingExprNode(ExprNode* node, IExprNodeDataProvider* aDataProvider);
        void EvaluateFunctionNode(ExprNode* node, IExprNodeDataProvider* aDataProvider);
        void EvaluateUnaryOperateNode(ExprNode* left, IExprNodeDataProvider* aDataProvider, ExprNode* node);
        void EvaluateIDNode(ExprNode* node, IExprNodeDataProvider* aDataProvider);
        void EvaluateConstNode(ExprNode* node);
        void EvaluateBinaryOperateNode(ExprNode* left, ExprNode* right, ExprNode* node, IExprNodeDataProvider* aDataProvider);

        void EvaluateOrOperateNode(ExprNode* left, ExprCustumNode* binarynode, ExprNode* right, IExprNodeDataProvider* aDataProvider);
        void EvaluateAndOperateNode(ExprNode* left, ExprCustumNode* binarynode, ExprNode* right, IExprNodeDataProvider* aDataProvider);
        void EvaluateNotEqualOperateNode(ExprNode* left, ExprNode* right, UnitMap& result, ExprCustumNode* binarynode);
        void EvaluateGreaterEqualOperateNode(ExprNode* left, ExprNode* right, UnitMap& result, ExprCustumNode* binarynode);
        void EvaluateGreaterOperateNode(ExprNode* left, ExprNode* right, UnitMap& result, ExprCustumNode* binarynode);
        void EvaluateLessEqualOperateNode(ExprNode* left, ExprNode* right, UnitMap& result, ExprCustumNode* binarynode);
        void EvaluateLessOperateNode(ExprNode* left, ExprNode* right, UnitMap& result, ExprCustumNode* binarynode);
        void EvaluateEqualOperateNode(ExprNode* left, ExprNode* right, UnitMap& result, ExprCustumNode* binarynode);
        void EvaluateModulusOperateNode(ExprNode* left, ExprNode* right, UnitMap& result, ExprCustumNode* binarynode);
        void EvaluateDivideOperateNode(ExprNode* left, ExprNode* right, UnitMap& result, ExprCustumNode* binarynode);
        void EvaluateMultiplyOperateNode(ExprNode* left, ExprNode* right, UnitMap& result, ExprCustumNode* binarynode);
        void EvaluateMinusOperateNode(ExprNode* left, ExprNode* right, UnitMap& result, ExprCustumNode* binarynode);
        void EvaluatePlusOperateNode(ExprNode* left, ExprNode* right, UnitMap& result, ExprCustumNode* binarynode);

        bool FindToken(const ExprNode* node, const wchar_t* tokenName) const;

    private:
        IExprEngine* m_pEngine;
        gcmp::OwnerPtr<ExprNode> m_opRootNode;
        std::vector<wchar_t> m_strExpression;
        ExprTokenScanner m_scanner; // 词法分析器
        ExprTokenType m_currentToken; // 当前Token
        bool m_isValid;
        bool m_isNull; // 是否为空
        int m_errorPos;
        EnErrorType m_errorType;
        std::vector<const wchar_t*> m_exprNodeName;
    };
}
